﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using CommerceML.Version205;
using API.Models;

namespace API.Core
{
    public partial class CommerceMLConverter
    {
        КоммерческаяИнформация rv = new КоммерческаяИнформация();

        public IEnumerable<V_OutgoingInvoices> Convert(КоммерческаяИнформация document)
        {
            foreach (var item in document.Items)
            {
                if (item is Документ)
                    yield return this.ConvertInvoice(item as Документ);
            }
        }

        private V_OutgoingInvoices ConvertInvoice(Документ document)
        {
            var invoice = new V_OutgoingInvoices();

            invoice.GUID_RECORD = Guid.NewGuid();

            invoice.DOC_ID = document.Ид;
            invoice.DOC_NUMBER = document.Номер;
            invoice.DOC_DATE = document.Дата;
            invoice.TOTAL_AMOUNT = document.Сумма;

            if (document.Контрагенты.Any(r => r.Роль == РольТип.Продавец))
            {
                invoice.COMPANY = ConvertCompany(document.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Продавец));
                invoice.COMPANY_GUID = invoice.COMPANY.GUID_RECORD;
            }

            if (document.Контрагенты.Any(r => r.Роль == РольТип.Покупатель))
            {
                invoice.CUSTOMER = ConvertCompany(document.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Покупатель));
                invoice.CUSTOMER_GUID = invoice.CUSTOMER.GUID_RECORD;
            }

            if (document.Контрагенты.Any(r => r.Роль == РольТип.Получатель))
            {
                invoice.LOCATION = this.ConvertCompanyLocation(document.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Получатель));
                invoice.LOCATION_GUID = invoice.LOCATION.GUID_RECORD;
            }

            invoice.TAX_AMOUNT = document.Налоги.Any() 
                ? document.Налоги.Sum(r => r.Сумма) 
                : 0;

            invoice.LINES = document.Товары
                .Select((r, i) => this.ConvertInvoiceLine(r, invoice.GUID_RECORD, i + 1))
                .OrderBy(r => r.ORDER_NUM)
                .ToArray();

            return invoice;
        }

        private WH_COMPANIES ConvertCompany(ДокументКонтрагент document)
        {
            var company = new WH_COMPANIES();

            company.EXT_KEY = document.Ид;
            company.COMPANY_NAME = document.Наименование;

            return company;
        }

        private WH_LOCATIONS ConvertCompanyLocation(ДокументКонтрагент document)
        {
            var location = new WH_LOCATIONS();

            //location.GUID_RECORD = Guid.NewGuid();

            location.EXT_KEY = document.Ид;
            location.LOCATION_NAME = document.Наименование;

            if (document.Адрес != null && document.Адрес.АдресноеПоле.Any(r => r.Тип == АдресТип.Почтовыйиндекс))
                location.POSTAL_CODE = document.Адрес.АдресноеПоле.SingleOrDefault(r => r.Тип == АдресТип.Почтовыйиндекс).Значение;

            if (document.Адрес != null && document.Адрес.АдресноеПоле.Any(r => r.Тип == АдресТип.Страна))
                location.COUNTRY = document.Адрес.АдресноеПоле.SingleOrDefault(r => r.Тип == АдресТип.Страна).Значение;

            if (document.Адрес != null && document.Адрес.АдресноеПоле.Any(r => r.Тип == АдресТип.Город))
                location.CITY = document.Адрес.АдресноеПоле.SingleOrDefault(r => r.Тип == АдресТип.Город).Значение;

            if (document.Адрес != null && document.Адрес.АдресноеПоле.Any(r => r.Тип == АдресТип.Улица))
                location.STREET = document.Адрес.АдресноеПоле.SingleOrDefault(r => r.Тип == АдресТип.Улица).Значение;

            if (document.Адрес != null && document.Адрес.АдресноеПоле.Any(r => r.Тип == АдресТип.Дом))
                location.BUILDING_NUMBER = document.Адрес.АдресноеПоле.SingleOrDefault(r => r.Тип == АдресТип.Дом).Значение;

            return location;
        }

        private V_OutgoingInvoiceLines ConvertInvoiceLine(ДокументТовар document, Guid ID, int orderNum = 0)
        {
            var invoiceLine = new V_OutgoingInvoiceLines();

            invoiceLine.PRICE = document.ЦенаЗаЕдиницу;
            invoiceLine.QUANTITY = document.Количество;
            invoiceLine.TOTAL = document.Сумма;

            invoiceLine.INVOICE_GUID = ID;
            invoiceLine.ORDER_NUM = short.Parse(orderNum.ToString());

            invoiceLine.ITEM = new WH_ITEMS()
            {
                EXT_KEY = document.Ид,
                ITEM_NAME = document.Наименование,
                ARTICLE = document.Артикул
            };

            invoiceLine.TAXES = document.СтавкиНалогов
                .Select(r => ConvertInvoiceLineTax(r, invoiceLine.TOTAL))
                .ToList();

            invoiceLine.TAX_TOTAL = document.Налоги.Any()
                ? invoiceLine.TAXES.Sum(r => r.AMOUNT)
                : 0;

            return invoiceLine;
        }

        private WH_INVOICE_LINES_TAXES ConvertInvoiceLineTax(ТоварСтавкаНалога document, decimal amount)
        {
            var rate = decimal.Parse(System.Text.RegularExpressions.Regex.Match(document.Ставка, @"\d+").Value);

            if (rate > 1)
                rate = rate / 100;

            return new WH_INVOICE_LINES_TAXES
            {
                AMOUNT = Math.Round(amount - (amount / (1 + rate)), 2),
                RATE = rate,
                TAX = new WH_TAXES
                {
                    TAX_NAME = document.Наименование
                }
            };
        }

    }

    public partial class CommerceMLConverter
    {
        public КоммерческаяИнформация Convert(IEnumerable<V_IncomingInvoices> invoices)
        {
            var document = new КоммерческаяИнформация();
            document.ВерсияСхемы = "2.05";
            document.ДатаФормирования = DateTime.Now;

            /// уберем ошибочные документы
            invoices = invoices
                .Where(r => r.LINES.All(n => n.ITEM != null))
                .Where(r => r.LOCATION != null);

            document.Items = invoices
                .Select(r => this.ConvertInoviceToDocument(r))
                .ToArray();

            return document;
        }

        private Документ ConvertInoviceToDocument(V_IncomingInvoices invoice)
        {
            var document = new Документ();
            document.Ид = invoice.GUID_RECORD.ToString();
            document.Номер = invoice.DOC_NUMBER;
            document.Дата = invoice.DOC_DATE.Date;
            //document.Время = invoice.DOC_DATE;
            document.Время = invoice.DOC_DATE.ToString("h:mm:ss");
            document.Валюта = "руб";
            document.Курс = "1";
            document.Сумма = invoice.TOTAL_AMOUNT;

            /// TODO:
            /// Сделать группировку по вложенным в налогам
            document.Налоги = new[] { 
                new ДокументНалог { Наименование = "НДС", Сумма = invoice.TAX_AMOUNT, УчтеноВСумме = true }
            };
            
            document.ХозОперация = ХозОперацияТип.Заказтовара;

            var seller = this.ConvertCompany(invoice.COMPANY);
            seller.Роль = РольТип.Продавец;

            var buyer = this.ConvertCompany(invoice.CUSTOMER);
            buyer.Роль = РольТип.Покупатель;
            buyer.Склад = new Склад
            {
                Ид = invoice.LOCATION.EXT_KEY,
                Наименование = invoice.LOCATION.LOCATION_NAME,
                Адрес = new Адрес
                {
                    Представление = String.Join(", ", new[] {
                    invoice.LOCATION.POSTAL_CODE,
                    invoice.LOCATION.COUNTRY,
                    invoice.LOCATION.CITY,
                    invoice.LOCATION.STREET,
                    invoice.LOCATION.BUILDING_NUMBER}),

                    АдресноеПоле = new АдресАдресноеПоле[] {
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Почтовыйиндекс,
                        Значение = invoice.LOCATION.POSTAL_CODE
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Страна,
                        Значение = invoice.LOCATION.COUNTRY
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Город,
                        Значение = invoice.LOCATION.CITY
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Улица,
                        Значение = invoice.LOCATION.STREET
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Дом,
                        Значение = invoice.LOCATION.BUILDING_NUMBER
                    },
                }
                },
                Комментарий = invoice.LOCATION.NOTE
            };

            //var recipient = this.ConvertCompanyLocation(invoice.LOCATION);
            //recipient.Роль = РольТип.Получатель;

            document.Контрагенты = new ДокументКонтрагент[] { seller, buyer };

            document.Товары = invoice.LINES
                .OrderBy(r => r.ORDER_NUM)
                .Select(r => this.ConvertInvoiceLine(r))
                .ToArray();

            return document;
        }

        private ДокументКонтрагент ConvertCompany(WH_COMPANIES company)
        {
            var document = new ДокументКонтрагент();

            document.Ид = company.EXT_KEY;
            document.Наименование = company.COMPANY_NAME;

            return document;
        }

        private ДокументКонтрагент ConvertCompanyLocation(WH_LOCATIONS location)
        {
            var document = new ДокументКонтрагент();

            document.Ид = location.EXT_KEY;
            document.Наименование = location.LOCATION_NAME;

            document.Адрес = new Адрес()
            {
                Представление = String.Join(", ", new[] {
                    location.POSTAL_CODE,
                    location.COUNTRY,
                    location.CITY,
                    location.STREET,
                    location.BUILDING_NUMBER}),

                АдресноеПоле = new АдресАдресноеПоле[] {
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Почтовыйиндекс,
                        Значение = location.POSTAL_CODE
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Страна,
                        Значение = location.COUNTRY
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Город,
                        Значение = location.CITY
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Улица,
                        Значение = location.STREET
                    },
                    new АдресАдресноеПоле()
                    {
                        Тип = АдресТип.Дом,
                        Значение = location.BUILDING_NUMBER
                    },
                }
            };

            return document;
        }

        private ДокументТовар ConvertInvoiceLine(V_IncomingInvoiceLines invoiceLine)
        {
            var document = new ДокументТовар
            {
                Ид = invoiceLine.ITEM.EXT_KEY,
                Артикул = invoiceLine.ITEM.ARTICLE,
                Наименование = invoiceLine.ITEM.ITEM_NAME,
                ЦенаЗаЕдиницу = invoiceLine.PRICE,
                Количество = invoiceLine.QUANTITY,
                Сумма = invoiceLine.TOTAL,
                //Сумма = invoiceLine.PRICE * invoiceLine.QUANTITY,
                Единица = "шт",
                КоличествоSpecified = true,
                Коэффициент = "1",
                СуммаSpecified = true,
                ЦенаЗаЕдиницуSpecified = true,
                Налоги = invoiceLine.TAXES.Select(r => this.ConvertInvoiceLineTax(r)).ToArray(),
                СтавкиНалогов = invoiceLine.TAXES.Select(r => this.ConvertInvoiceLineTaxRate(r)).ToArray(),
            };

            return document;
        }

        private ДокументТоварНалог ConvertInvoiceLineTax(WH_INVOICE_LINES_TAXES document)
        {
            return new ДокументТоварНалог
            {
                Сумма = document.AMOUNT,
                Наименование = document.TAX.TAX_NAME,
                УчтеноВСумме = true
            };
        }

        private ТоварСтавкаНалога ConvertInvoiceLineTaxRate(WH_INVOICE_LINES_TAXES document)
        {
            return new ТоварСтавкаНалога
            {
                Наименование = document.TAX.TAX_NAME,
                Ставка = Math.Round((document.RATE * 100), 0).ToString() + "%",
            };
        }
    }

}